using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Web;
using System.Collections;
using System.Text;
using System.Web.Security;
using System.Web.Caching;
using System.Web.UI;
using System.Web.SessionState;
using System.IO;
using System.Configuration;


namespace Univar
{
	/// <summary>
	/// Static object to get/set Session, Cookie and Querystring variables
	/// </summary>
	public static partial class StorageUser
	{
		public static string HTTPCONTEXT_NOT_AVAILABLE_ERROR_MESSAGE =
				"The HttpContext property or argument needs to be referenced before using page bound storages.";

		private static HttpContext _context;
		public static HttpContext Context
		{
			get
			{
				return HttpContext.Current;
			}
			set
			{
				_context = HttpContext.Current = value;
			}
		}

		///<summary>
		///Use the following sample to add the session file configurations to the web.config
		///<code>
		///	&lt;configuration>
		///		&lt;appSettings>
		///			&lt;add key="InFileCacheUserKey" value="MyInFileCacheUserKey"/>
		///			&lt;add key="InFileCacheFolderPath" value="~/MyInFileCaches"/>
		///			&lt;add key="InFileCacheDeployedFolderPath" value="c:\MyInFileCaches"/>
		///		&lt;/appSettings>
		///	&lt;/configuration>
		///</code>
		///</summary>
		public static string DefaultUserNameKey
		{
			get { return ConfigurationManager.AppSettings.Get("InFileCacheUserKey") ?? "InFileCacheUserKey"; }
		}

		public static bool IsAuthenticated
		{
			get
			{
				return (StorageUser.Context.User != null
					&& StorageUser.Context.User.Identity != null
					&& !string.IsNullOrEmpty(StorageUser.Context.User.Identity.Name));
			}
		}

		public static string Name
		{
			get
			{
				if (StorageUser.Context.User.Identity.IsAuthenticated)
				{
					return StorageUser.Context.User.Identity.Name;
				}
				else
				{
					return !string.IsNullOrEmpty(StorageUser.Context.Profile.UserName) ? StorageUser.Context.Profile.UserName : Storage.Cookie.Get("Userkey");
				}
			}
			set
			{
				Storage.Cookie.Set("Userkey", value, Storage.Cookie.DefaultLifeTime);
			}
		}

		public static string GetLocation(HttpContext httpContext, string pageNotFoundErrorMessage)
		{
			if (httpContext == null)
				throw new ArgumentNullException(pageNotFoundErrorMessage ??
					"A HttpContext reference is not available for this operation to proceed.", "HttpContext reference");

			return httpContext.Request.Url.AbsoluteUri.Split('?')[0];
		}

		public static string GetUserID()
		{
			if (!StorageUser.Context.Profile.IsAnonymous)
				return Membership.GetUser(StorageUser.Context.Profile.UserName).ProviderUserKey.ToString();
			else
				return null;
		}

		public static string GetSessionID()
		{
			return StorageUser.Context.Session.SessionID;
		}

		public static string GetAutoGeneragedCookieID(TimeSpan? lifeTime)
		{
			if (Storage.Cookie.Get(DefaultUserNameKey) == null)
				CreateMachineIdentifierCookie(lifeTime);

			return Storage.Cookie.Get(DefaultUserNameKey, false, true, true);
		}

		/// <summary>
		/// Create a new text file on the server to store the user data. 
		/// </summary>
		/// <returns>The new unique user Identifier stored in the user cookie which is encrypted
		/// using the CookieEncryptor class in tamper proof manner.</returns>
		public static string CreateMachineIdentifierCookie(TimeSpan? lifeTime)
		{
			string userId;
			do
				userId = "User_" + Guid.NewGuid().ToString();
			while (File.Exists(Storage.InFileCache.GetFilePath(null, userId))); // Create new user id if it already exists.

			Storage.Cookie.Set(DefaultUserNameKey, userId, lifeTime ?? TimeSpan.MaxValue, false, true);

			// Verify that the cookie has been successfully created.
			if (userId == Storage.Cookie.Get(DefaultUserNameKey, false, true, true))
				return userId;
			else
				throw new Exception("Browser does not accept cookies.");
		}

		public static string GetLocationKey(string childKey, HttpContext httpContext, string pageNotFoundErrorMessage)
		{
			return GetLocation(httpContext, pageNotFoundErrorMessage) + Global.KeyDelimiter + childKey;
		}

		public static string GetUserKey(string childKey)
		{
			return GetUserID() + Global.KeyDelimiter + childKey;
		}

		public static string GetSessionKey(string childKey)
		{
			return GetSessionID() + Global.KeyDelimiter + childKey;
		}

		public static string GetAutoGeneragedCookieKey(string childKey, TimeSpan cookieLifetimeForBrowserLevelID)
		{
			return GetAutoGeneragedCookieID(cookieLifetimeForBrowserLevelID) + Global.KeyDelimiter + childKey;
		}

		public static string GetUserKeyByScope(string childKey, Scopes scope, HttpContext httpContext, TimeSpan? cookieLifetimeForBrowserLevelID)
		{
			string scopeKey;

			switch (scope)
			{
				case Scopes.Default:
					scopeKey = "";
					break;
				case Scopes.Location:
					scopeKey = GetLocation(httpContext, HTTPCONTEXT_NOT_AVAILABLE_ERROR_MESSAGE);
					break;
				case Scopes.User:
					scopeKey = GetUserID();
					break;
				case Scopes.Session:
					scopeKey = GetSessionID();
					break;
				case Scopes.Browser:
					scopeKey = GetAutoGeneragedCookieID(cookieLifetimeForBrowserLevelID.Value);
					break;
				default:
					scopeKey = null;
					break;
			}

			return string.IsNullOrEmpty(scopeKey)
				? scopeKey + childKey
				: scopeKey + Global.KeyDelimiter + childKey;
		}
	}
}
